#pragma once
#ifndef _ID_PRODUCER_H_
#define _ID_PRODUCER_H_
#ifdef WIN32
#pragma execution_character_set("utf-8")
#endif

#include <iostream>
#include <mutex>
#include <exception>
#include <sstream>
#include <chrono>


using namespace std;

typedef unsigned long long uint64;


class IdProducer {

public:

	static uint64 nextId();

private:


	/// <summary>
	/// 禁用复制构造函数
	/// </summary>
	/// <param name="other"></param>
	IdProducer(const IdProducer& other) {};

	//创建实例
	IdProducer(uint64 beginTime = -1, uint64 dataCenterId = 0L, uint64 workerId = 0L);

	/// <summary>
	/// 获取雪花算法生成的Id
	/// </summary>
	/// <returns></returns>
	uint64 getNextId();

	/// <summary>
	/// 禁用外部赋值操作
	/// </summary>
	/// <param name="other"></param>
	void operator=(const IdProducer& other) {};

	//生成时间戳
	uint64 timeGen();

	//阻塞到下一个时间戳
	uint64 tilNextSpan(uint64 lastTimestamp);

private:

	const uint64 workerIdBits = 5L;								//工作机编号的长度

	const uint64 datacenterIdBits = 5L;							//数据中心编号的长度

	const uint64 maxWorkerId = -1L ^ (-1L << workerIdBits);		//工作机编号最大值

	const uint64 maxDatacenterId = -1L ^ (-1L << workerIdBits);	//数据中心编号最大值

	const uint64 sequenceBits = 12L;							//序列号数据长度

	const uint64 workerIdShift = sequenceBits;					//工作机编号左移位数

	const uint64 dataCenterIdShift = sequenceBits + workerIdBits;	//数据中心左移位数

	const uint64 timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;	//时间戳左移位数

	const uint64 sequenceMask = -1L ^ (-1L << sequenceBits);		//生成序列的掩码，这里为4095

	uint64 datacenterId;					//数据中心Id

	uint64 workerId;						//计算机ID

	uint64 startTime;						//起始时间

	uint64 sequence = 0L;					//序列号

	uint64 lastTimestamp = 0L;				//记录上一个时间戳

	std::mutex mutex;						//使线程安全的锁

	static IdProducer* producer;			//单一实例
};


#endif